home *** CD-ROM | disk | FTP | other *** search
-
- #
- # sets implemented using mappings
- # Copyright Aaron Robert Watters, 1994
- #
- # these only work for "immutable" elements.
- # probably not terribly efficient, but easy to implement
- # and not as slow as concievably possible.
-
- def NewSet(Sequence):
- Result = {}
- for Elt in Sequence:
- Result[Elt] = 1
- return Result
-
- def Empty(Set):
- if Set == {}:
- return 1
- else:
- return 0
-
- def get_elts(Set):
- return Set.keys()
-
- def member(Elt,Set):
- return Set.has_key(Elt)
-
- # in place mutators:
- # returns if no change otherwise 1
-
- def addMember(Elt,Set):
- change = 0
- if not Set.has_key(Elt):
- Set[Elt] = 1
- change = 1
- return change
-
- def Augment(Set, OtherSet):
- change = 0
- for Elt in OtherSet.keys():
- if not Set.has_key(Elt):
- Set[Elt] = 1
- change = 1
- return change
-
-
- def Mask(Set, OtherSet):
- change = 0
- for Elt in OtherSet.keys():
- if Set.has_key(Elt):
- del Set[Elt]
- change = 1
- return change
-
- # side effect free functions
-
- def Intersection(Set1, Set2):
- Result = {}
- for Elt in Set1.keys():
- if Set2.has_key(Elt):
- Result[Elt] = 1
- return Result
-
- def Difference(Set1, Set2):
- Result = {}
- for Elt in Set1.keys():
- if not Set2.has_key(Elt):
- Result[Elt] = 1
- return Result
-
- def Union(Set1,Set2):
- Result = {}
- Augment(Result,Set1)
- Augment(Result,Set2)
- return Result
-
- def Subset(Set1,Set2):
- Result = 1
- for Elt in Set1.keys():
- if not Set2.has_key(Elt):
- Result = 0
- return Result # nonlocal
- return Result
-
- def Same(Set1,Set2):
- if Subset(Set1,Set2) and Subset(Set2,Set1):
- return 1
- else:
- return 0
-
- # directed graphs as Dictionaries of Sets
- # also only works for immutable nodes
-
- def NewDG(pairlist):
- Result = {}
- for (source,dest) in pairlist:
- AddArc(Result, source, dest)
- return Result
-
- def GetPairs(Graph):
- result = []
- Sources = Graph.keys()
- for S in Sources:
- Dests = get_elts( Graph[S] )
- ThesePairs = [None] * len(Dests)
- for i in range(0,len(Dests)):
- D = Dests[i]
- ThesePairs[i] = (S, D)
- result = result + ThesePairs
- return result
-
- def AddArc(Graph, Source, Dest):
- change = 0
- if Graph.has_key(Source):
- Adjacent = Graph[Source]
- if not member(Dest,Adjacent):
- addMember(Dest,Adjacent)
- change = 1
- else:
- Graph[Source] = NewSet( [ Dest ] )
- change = 1
- return change
-
- def Neighbors(Graph,Source):
- if Graph.has_key(Source):
- return get_elts(Graph[Source])
- else:
- return []
-
- def HasArc(Graph, Source, Dest):
- result = 0
- if Graph.has_key(Source) and member(Dest, Graph[Source]):
- result = 1
- return result
-
- def Sources(Graph):
- return Graph.keys()
-
- # when G1, G2 and G3 are different graphs this results in
- # G1 = G1 U ( G2 o G3 )
- # If G1 is identical to one of G2,G3 the result is somewhat
- # nondeterministic (depends on dictionary implementation).
- # However, guaranteed that AddComposition(G,G,G) returns
- # G1 U (G1 o G1) <= G <= TC(G1)
- # where G1 is G's original value and TC(G1) is its transitive closure
- # hence this function can be used for brute force transitive closure
- #
- def AddComposition(G1, G2, G3):
- change = 0
- for G2Source in Sources(G2):
- for Middle in Neighbors(G2,G2Source):
- for G3Dest in Neighbors(G3, Middle):
- if not HasArc(G1, G2Source, G3Dest):
- change = 1
- AddArc(G1, G2Source, G3Dest)
- return change
-
- # in place transitive closure of a graph
- def TransClose(Graph):
- change = AddComposition(Graph, Graph, Graph)
- somechange = change
- while change:
- change = AddComposition(Graph, Graph, Graph)
- if not somechange:
- somechange = change
- return somechange
-
- ########### SQueue stuff
- #
- # A GrabBag should be used to hold objects temporarily for future
- # use. You can put things in and take them out, with autodelete
- # that's all!
-
- # make a new baggy with nothing in it
- # BG[0] is insert cursor BG[1] is delete cursor, others are elts
- #
- OLD = 1
- NEW = 0
- START = 2
- def NewBG():
- B = [None]*8 #default size
- B[OLD] = START
- B[NEW] = START
- return B
-
- def BGempty(B):
- # other ops must maintain this: old == new iff empty
- return B[OLD] == B[NEW]
-
- # may return new, larger structure
- # must be used with assignment... B = BGadd(e,B)
- def BGadd(elt, B):
- cursor = B[NEW]
- oldlen = len(B)
- # look for an available position
- while B[cursor] != None:
- cursor = cursor+1
- if cursor >= oldlen: cursor = START
- if cursor == B[NEW]: #back to beginning
- break
- # resize if wrapped
- if B[cursor] != None:
- B = B + [None] * oldlen
- cursor = oldlen
- B[OLD] = START
- if B[cursor] != None:
- raise IndexError, "can't insert?"
- # add the elt
- B[cursor] = (elt,)
- B[NEW] = cursor
- # B nonempty so OLD and NEW should differ.
- if B[OLD] == cursor:
- B[NEW] = cursor + 1
- if B[NEW]<=len(B): B[NEW] = START
- return B
-
- def BGgetdel(B):
- # find something to delete:
- cursor = B[OLD]
- blen = len(B)
- while B[cursor]==None:
- cursor = cursor+1
- if cursor>=blen: cursor = START
- if cursor == B[OLD]: break # wrapped
- if B[cursor] == None:
- raise IndexError, "delete from empty grabbag(?)"
- # test to see if bag is empty (position cursor2 at nonempty slot)
- cursor2 = cursor+1
- if cursor2>=blen: cursor2 = START
- while B[cursor2]==None:
- cursor2 = cursor2+1
- if cursor2>=blen: cursor2 = START
- # since B[cursor] not yet deleted while will terminate
- # get and delete the elt
- (result,) = B[cursor]
- B[cursor] = None
- # cursor == cursor2 iff bag is empty
- B[OLD] = cursor2
- if B[NEW] == cursor2: B[NEW] = cursor
- return result
-
- def BGtest(n):
- B = NewBG()
- rn = range(n)
- rn2 = range(n-2)
- for i in rn:
- for j in rn:
- B = BGadd( (i,j), B)
- B = BGadd( (j,i), B)
- x = BGgetdel(B)
- for j in rn2:
- y = BGgetdel(B)
- print (i, x, y)
- return B
-